#include "EditBox.h"
#include "../GuiApi.h"
#include "../UsefullApi.h"
#include "vmgraph.h"
#include "vmstdlib.h"
#include "vmchset.h"

static VMINT cur_editbox_hctrl;
static VMINT save_prev_ed_addr;

void EditBoxSetContent(VMINT hctrl, VMWSTR text)
{
	struct control_editbox *p = (struct control_editbox *)hctrl;
	if(text)
	{
		vm_wstrcpy(p->text, text);
	}
}

VMWSTR EditBoxGetContent(VMINT hctrl)
{
	struct control_editbox *p = (struct control_editbox *)hctrl;
	return p->text;
}

void EditBoxInputCallback(VMINT state, VMWSTR text)
{
	VMINT hctrl;
	hctrl = save_prev_ed_addr;
	if(state == TRUE)
	{
		EditBoxSetContent(hctrl, text);
		RefreshEditBox(hctrl);
	}
}

void EditBoxInput(VMINT hctrl)
{
	struct control_editbox *p = (struct control_editbox *)hctrl;
	save_prev_ed_addr = hctrl;
	if(p->default_text)
	{
		VMWSTR pStr = ascii_to_ucs2(p->default_text);
		vm_input_text3(pStr, p->text_max_size, p->type, EditBoxInputCallback);
		free_str(pStr);
		p->default_text = NULL;
	}
	else
	{
		vm_input_text3(p->text, p->text_max_size, p->type, EditBoxInputCallback);
	}
}

void DrawEditBoxPass(VMBYTE* frame_buf, VMINT hctrl, VMWSTR text, VMINT x, VMINT y, VMINT width, VMUINT16 color)
{
	struct control_editbox *p = (struct control_editbox *)hctrl;
	VMWCHAR star[2] = {0};
	VMWSTR pPass;
	VMWSTR pStr, pSrc = text;
	VMINT i;
	VMINT str_width;
	VMINT str_len = vm_wstrlen(pSrc);
	VMINT malloc_size;
	
	vm_ascii_to_ucs2(star, 4, "*");
	
	if(pSrc == NULL)
	{
		return;
	}

	if(p->type == EDITBOX_TYPE_PASSWORD)
	{
		malloc_size = (str_len+1)*sizeof(VMWCHAR);
		pPass = (VMWSTR)vm_malloc(malloc_size);
		memset(pPass, 0, malloc_size);

		for(i=0;i<str_len;i++)
		{
			pPass[i] = star[0];
		}
		pPass[str_len] = 0;
		pSrc = pPass;
	}

	str_width = vm_graphic_get_string_width(pSrc);
	if(str_width < width)
	{
		DrawTextUCS2(frame_buf, pSrc, x, y, color);
		free_str(pPass);
		return;
	}
	
	malloc_size = str_len*sizeof(VMWCHAR);
	pStr = (VMWSTR)vm_malloc(malloc_size);
	memset(pStr, 0, malloc_size);

	for(i=0;i<str_len;i++)
	{
		pStr[i] = pSrc[i];
		str_width = vm_graphic_get_string_width(pStr);
		if(str_width >= width)
		{
			DrawTextUCS2(frame_buf, pStr, x, y, color);
			break;
		}
	}
	free_str(pStr);
	free_str(pPass);
}


void DrawEditBoxText(VMBYTE* frame_buf, VMINT hctrl, VMWSTR text, VMINT x, VMINT y, VMINT width, VMUINT16 color)
{
	struct control_editbox *p = (struct control_editbox *)hctrl;
	VMWSTR pStr, pSrc = text;
	VMINT i;
	VMINT str_width;
	VMINT str_len = vm_wstrlen(pSrc);
	VMINT malloc_size;
	if(pSrc == NULL)
	{
		return;
	}

	str_width = vm_graphic_get_string_width(pSrc);
	if(str_width < width)
	{
		DrawTextUCS2(frame_buf, pSrc, x, y, color);
		return;
	}
	
	malloc_size = str_len*sizeof(VMWCHAR);
	pStr = (VMWSTR)vm_malloc(malloc_size);
	memset(pStr, 0, malloc_size);

	for(i=0;i<str_len;i++)
	{
		pStr[i] = pSrc[i];
		str_width = vm_graphic_get_string_width(pStr);
		if(str_width >= width)
		{
			pStr[i] = 0;
			DrawTextUCS2(frame_buf, pStr, x, y, color);
			break;
		}
	}
	free_str(pStr);
}

void DrawEditBoxRelease(VMINT hctrl)
{
	struct control_editbox *p = (struct control_editbox *)hctrl;
	VMUINT8* frame_buffer = GetHDFrameBuffer();
	VMINT x, y, width, height;
	VMINT xf, yf, font_height;
	VMSTR pSrc;
	VMWSTR pStr;
	VMUINT16 color;

	x = p->p.p.x;
	y = p->p.p.y;
	width = p->p.p.width;
	height = p->p.p.height;
	
	vm_graphic_set_clip(x, y, x + width, y + height);

	DrawRoundRect(frame_buffer, x, y, width, height, RECT_CORNER_WIDTH, 2, V_RGB(171, 187, 208), V_RGB(254, 254, 254));

	font_height = vm_graphic_get_character_height();
	
	xf = x + RECT_CORNER_WIDTH;
	yf = y + (height - font_height)/2;

	if(vm_wstrlen(p->text) > 0)
	{
		pStr = p->text;
		if(p->type == EDITBOX_TYPE_PASSWORD)
		{
			DrawEditBoxPass(frame_buffer, hctrl, pStr, xf, yf, width - 2*RECT_CORNER_WIDTH, COLOR_EDITBOX_TEXT);
		}
		else
		{
			DrawEditBoxText(frame_buffer, hctrl, pStr, xf, yf, width - 2*RECT_CORNER_WIDTH, COLOR_EDITBOX_TEXT);
		}
	}
	else
	{
		if(p->default_text != NULL)
		{
			pSrc = p->default_text;
			color = COLOR_EDITBOX_TEXT;
			pStr = ascii_to_ucs2(pSrc);
			if(p->type == EDITBOX_TYPE_PASSWORD)
			{
				DrawEditBoxPass(frame_buffer, hctrl, pStr, xf, yf, width - 2*RECT_CORNER_WIDTH, color);
			}
			else
			{
				DrawEditBoxText(frame_buffer, hctrl, pStr, xf, yf, width - 2*RECT_CORNER_WIDTH, color);
			}
			free_str(pStr);
			goto _END;
		}
		if(p->hint_msg != NULL)
		{
			pSrc = p->hint_msg;
			color = COLOR_EDITBOX_HINT_TEXT;
			pStr = ascii_to_ucs2(pSrc);
			DrawEditBoxText(frame_buffer, hctrl, pStr, xf, yf, width - 2*RECT_CORNER_WIDTH, color);
			free_str(pStr);
			goto _END;
		}
	}
_END:
	UpdateScreen();
	return;
}

void DrawEditBoxPress(VMINT hctrl)
{
	struct control_editbox *p = (struct control_editbox *)hctrl;
	VMUINT8* frame_buffer = GetHDFrameBuffer();
	VMINT x, y, width, height;
	VMINT xf, yf, font_height;
	VMSTR pSrc;
	VMWSTR pStr;
	VMUINT16 color;
	
	x = p->p.p.x;
	y = p->p.p.y;
	width = p->p.p.width;
	height = p->p.p.height;

	vm_graphic_set_clip(x, y, x + width, y + height);
	
	DrawRoundRect(frame_buffer, x, y, width, height, RECT_CORNER_WIDTH, 2, COLOR_RECT_FOCUSED, COLOR_RECT_FILL);

	font_height = vm_graphic_get_character_height();
	
	xf = x + RECT_CORNER_WIDTH;
	yf = y + (height - font_height)/2;

	if(vm_wstrlen(p->text) > 0)
	{
		pStr = p->text;
		if(p->type == EDITBOX_TYPE_PASSWORD)
		{
			DrawEditBoxPass(frame_buffer, hctrl, pStr, xf, yf, width - 2*RECT_CORNER_WIDTH, COLOR_EDITBOX_TEXT);
		}
		else
		{
			DrawEditBoxText(frame_buffer, hctrl, pStr, xf, yf, width - 2*RECT_CORNER_WIDTH, COLOR_EDITBOX_TEXT);
		}
	}
	else
	{
		if(p->default_text != NULL)
		{
			pSrc = p->default_text;
			color = COLOR_EDITBOX_TEXT;
			pStr = ascii_to_ucs2(pSrc);
			if(p->type == EDITBOX_TYPE_PASSWORD)
			{
				DrawEditBoxPass(frame_buffer, hctrl, pStr, xf, yf, width - 2*RECT_CORNER_WIDTH, color);
			}
			else
			{
				DrawEditBoxText(frame_buffer, hctrl, pStr, xf, yf, width - 2*RECT_CORNER_WIDTH, color);
			}
			free_str(pStr);
			goto _END;
		}
		if(p->hint_msg != NULL)
		{
			pSrc = p->hint_msg;
			color = COLOR_EDITBOX_HINT_TEXT;
			pStr = ascii_to_ucs2(pSrc);
			DrawEditBoxText(frame_buffer, hctrl, pStr, xf, yf, width - 2*RECT_CORNER_WIDTH, color);
			free_str(pStr);
			goto _END;
		}
	}
_END:
	UpdateScreen();
	return;
}


void TouchEditBoxEventHandle(VMINT tevent, VMINT x, VMINT y)
{
	struct control_editbox *p = (struct control_editbox *)cur_editbox_hctrl;

	if(p->p.is_actived == FALSE)
	{
		return;
	}
	
	switch(tevent)
	{
	case GUI_PEN_DOWN:
		DrawEditBoxPress(cur_editbox_hctrl);
		break;
	case GUI_PEN_MOVE:
		DrawEditBoxRelease(cur_editbox_hctrl);
		break;
	case GUI_PEN_UP:
		EditBoxInput(cur_editbox_hctrl);
		if(!p->p.is_focused)
		{
			DrawEditBoxRelease(cur_editbox_hctrl);
		}
		break;
	}
}

void EditBoxRegisterKeyHandle(void)
{

}

VMINT CreateEditBox(VMSTR default_text, VMINT is_actived, VMINT x, VMINT y, VMINT width, VMINT height, VMSTR hint_msg, VMINT max_size, VMINT type)
{
	VMINT hctrl = (VMINT)vm_malloc(sizeof(struct control_editbox));
	struct control_editbox* p;
	if(hctrl == NULL)
	{
		return -1;
	}

	p = (struct control_editbox*)hctrl;
	memset(p, 0, sizeof(struct control_editbox));
	p->p.ctrl_id = DM_EDITBOX;
	strcat(p->p.ctrl_name, "EditBox");
	p->p.is_focused = FALSE;
	p->p.DrawStateRelease = DrawEditBoxRelease;
	p->p.DrawStatePress = DrawEditBoxPress;
	p->p.touch_event_handle = TouchEditBoxEventHandle;
	p->p.p.x = x;
	p->p.p.y = y;
	p->p.p.width = width;
	p->p.p.height = height;

	p->hint_color = COLOR_EDITBOX_HINT_TEXT;
	p->text_color = COLOR_EDITBOX_TEXT;
	p->text_max_size = max_size;
	p->type = type;
	p->p.is_actived = is_actived;
	
	if(hint_msg == NULL)
	{
		p->hint_msg = NULL;
	}
	else
	{
		p->hint_msg = hint_msg;
	}
		
	if(default_text == NULL)
	{
		p->default_text = NULL;
	}
	else
	{
		p->default_text = default_text;
	}

	p->text = (VMWSTR)vm_malloc(sizeof(VMWCHAR)*max_size);
	memset(p->text, 0, sizeof(VMWCHAR)*max_size);

	cur_editbox_hctrl = hctrl;
	return hctrl;
}

void ShowEditBox(VMINT hctrl)
{
	struct control_editbox *p = (struct control_editbox *)hctrl;
	
	if(p->p.is_actived == FALSE)
	{
		return;
	}
	
	if(p->p.is_focused)
	{
		DrawEditBoxPress(hctrl);
	}
	else
	{
		DrawEditBoxRelease(hctrl);
	}
}

void RefreshEditBox(VMINT hctrl)
{
	ShowEditBox(hctrl);	
}

void FreeEditBox(VMINT hctrl)
{
	struct control_editbox *p = (struct control_editbox *)hctrl;
	
	if(p->text)
	{
		vm_free(p->text);
		p->text = NULL;
	}

	vm_free(p);

	cur_editbox_hctrl = NULL;
	save_prev_ed_addr = NULL;
}

void RegisterCurFocusedEditBox(VMINT hctrl)
{
	cur_editbox_hctrl = hctrl;
}
